{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "6cce5e50",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit import QuantumCircuit, qasm3\n",
    "from quantum_chip import QuantumChip\n",
    "from hardware import HardwareParams\n",
    "from qrmove_compiler import QRMoveCompiler\n",
    "from utils import get_quantum_circuit\n",
    "import math\n",
    "from func_timeout import func_timeout, FunctionTimedOut\n",
    "\n",
    "\n",
    "# Default Settings\n",
    "# quantum_alg: bv\n",
    "# MRP_CP_ratio: 10\n",
    "# extra_qubit_ratio: 15%\n",
    "# qubit_num: 30\n",
    "\n",
    "\n",
    "def experiment(quantum_alg, qubit_num, extra_qubit_num, MRP_CP_ratio):\n",
    "    \"\"\"\n",
    "    quantum_alg: 量子算法\n",
    "    qubit_num: 量子比特数量\n",
    "    extra_qubit_ratio: 额外比特比例\n",
    "    MRP_CP_ratio: MRP/CP 比例\n",
    "    \"\"\"\n",
    "    try:\n",
    "        quantum_circuit: QuantumCircuit = get_quantum_circuit(quantum_alg, qubit_num)\n",
    "        quantum_chip = QuantumChip(\"square\", 50)\n",
    "        hardware_param = HardwareParams(\n",
    "            time_1q=300.0,  # 单比特门时间\n",
    "            time_2q=300.0,  # 双比特门时间\n",
    "            time_meas=300 * MRP_CP_ratio,  # 测量时间\n",
    "            time_reset=0,  # 重置时间\n",
    "        )\n",
    "        qmc = QRMoveCompiler(\n",
    "            quantum_circuit,\n",
    "            quantum_chip,\n",
    "            hardware_param,\n",
    "            math.ceil(extra_qubit_num),\n",
    "        )\n",
    "        (\n",
    "            start_depth,\n",
    "            start_width,\n",
    "            qr_map_depth,\n",
    "            qr_map_width,\n",
    "            qr_move_depth,\n",
    "            qr_move_width,\n",
    "        ) = qmc.compile_program()\n",
    "\n",
    "        # print(\n",
    "        #     f\"-- 运行结果: start_depth {start_depth}, start_width {start_width}, qr_map_depth {qr_map_depth}, qr_map_width {qr_map_width}, qr_move_depth {qr_move_depth}, qr_move_width {qr_move_width} --\"\n",
    "        # )\n",
    "\n",
    "        return (\n",
    "            start_depth,\n",
    "            start_width,\n",
    "            qr_map_depth,\n",
    "            qr_map_width,\n",
    "            qr_move_depth,\n",
    "            qr_move_width,\n",
    "        )\n",
    "\n",
    "    except Exception as e:\n",
    "        print(f\"Experiment failed with error: {e}\")\n",
    "        return 0, 0, 0, 0, 0, 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "3619e0a8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "alg: bv, extra_num: 1\n",
      "-- 运行结果: start_depth 24, start_width 30, qr_map_depth 141, qr_map_width 2, qr_move_depth 75, qr_move_width 3 --\n",
      "alg: qaoa, extra_num: 1\n",
      "-- 运行结果: start_depth 145, start_width 30, qr_map_depth 202, qr_map_width 27, qr_move_depth 175, qr_move_width 28 --\n",
      "alg: mod, extra_num: 1\n",
      "-- 运行结果: start_depth 13, start_width 30, qr_map_depth 181, qr_map_width 2, qr_move_depth 181, qr_move_width 2 --\n",
      "alg: mul, extra_num: 1\n",
      "-- 运行结果: start_depth 125, start_width 30, qr_map_depth 341, qr_map_width 3, qr_move_depth 309, qr_move_width 4 --\n",
      "alg: qram, extra_num: 1\n",
      "-- 运行结果: start_depth 13, start_width 30, qr_map_depth 181, qr_map_width 3, qr_move_depth 157, qr_move_width 4 --\n",
      "alg: rd, extra_num: 1\n",
      "-- 运行结果: start_depth 16, start_width 30, qr_map_depth 169, qr_map_width 3, qr_move_depth 115, qr_move_width 4 --\n",
      "alg: sym, extra_num: 1\n",
      "-- 运行结果: start_depth 11, start_width 30, qr_map_depth 301, qr_map_width 1, qr_move_depth 151, qr_move_width 2 --\n",
      "alg: xor, extra_num: 1\n",
      "-- 运行结果: start_depth 14, start_width 30, qr_map_depth 183, qr_map_width 4, qr_move_depth 183, qr_move_width 4 --\n"
     ]
    }
   ],
   "source": [
    "# Default Settings\n",
    "# quantum_alg: bv\n",
    "# MRP_CP_ratio: 10\n",
    "# extra_qubit_ratio: 15%\n",
    "# qubit_num: 30\n",
    "# bv qaoa mod mul qram rd sym xor\n",
    "# for alg in [\"xor\"]:\n",
    "for alg in [\"bv\", \"qaoa\", \"mod\", \"mul\", \"qram\", \"rd\", \"sym\", \"xor\"]:\n",
    "    for extra_num in [1]:\n",
    "        qubit_num = 30\n",
    "        mrp_ratio = 10\n",
    "        (\n",
    "            start_depth,\n",
    "            start_width,\n",
    "            qr_map_depth,\n",
    "            qr_map_width,\n",
    "            qr_move_depth,\n",
    "            qr_move_width,\n",
    "        ) = experiment(alg, qubit_num, extra_num, mrp_ratio)\n",
    "        print(f\"alg: {alg}, extra_num: {extra_num}\")\n",
    "        print(\n",
    "            f\"-- 运行结果: start_depth {start_depth}, start_width {start_width}, qr_map_depth {qr_map_depth}, qr_map_width {qr_map_width}, qr_move_depth {qr_move_depth}, qr_move_width {qr_move_width} --\"\n",
    "        )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b66604cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def experiment_with_timeout(\n",
    "    quantum_alg, qubit_num, extra_qubit_num, MRP_CP_ratio, timeout=60 * 30\n",
    "):\n",
    "    \"\"\"\n",
    "    带超时控制的实验函数\n",
    "    timeout: 超时时间（秒），默认5分钟\n",
    "    \"\"\"\n",
    "    try:\n",
    "        result = func_timeout(\n",
    "            timeout,\n",
    "            experiment,\n",
    "            args=(quantum_alg, qubit_num, extra_qubit_num, MRP_CP_ratio),\n",
    "        )\n",
    "        return result\n",
    "    except FunctionTimedOut:\n",
    "        print(f\"Experiment timed out after {timeout} seconds\")\n",
    "        return 0, 0, 0, 0, 0, 0\n",
    "\n",
    "\n",
    "def experiment_var_extra_ratio_alg():\n",
    "    import csv\n",
    "    import os\n",
    "\n",
    "    # 创建结果文件夹\n",
    "    os.makedirs(\"results\", exist_ok=True)\n",
    "\n",
    "    # 创建CSV文件并写入表头\n",
    "    csv_file = \"results/experiment_results.csv\"\n",
    "    with open(csv_file, mode=\"w\", newline=\"\") as file:\n",
    "        writer = csv.writer(file)\n",
    "        writer.writerow(\n",
    "            [\n",
    "                \"Algorithm\",\n",
    "                \"Extra_Ratio\",\n",
    "                \"Qubit_Num\",\n",
    "                \"Avg_Start_Depth\",\n",
    "                \"Avg_Start_Width\",\n",
    "                \"Avg_QR_Map_Depth\",\n",
    "                \"Avg_QR_Map_Width\",\n",
    "                \"Avg_QR_Move_Depth\",\n",
    "                \"Avg_QR_Move_Width\",\n",
    "                \"Valid_Experiments\",\n",
    "            ]\n",
    "        )\n",
    "\n",
    "    # 存储每个参数组合的任务结果\n",
    "    all_tasks = []\n",
    "\n",
    "    # 创建所有参数组合\n",
    "    for alg in [\"bv\", \"vqa\", \"qaoa\", \"qft\", \"mul\", \"rd\", \"xor\"]:\n",
    "        for extra_ratio in [0.1, 0.2, 0.3]:\n",
    "            qubit_num = 30\n",
    "            all_tasks.append((alg, extra_ratio, qubit_num))\n",
    "\n",
    "    # 为每个参数组合执行50次实验\n",
    "    def run_experiments_for_params(alg, extra_ratio, qubit_num):\n",
    "        results = []\n",
    "        for _ in range(50):\n",
    "            (\n",
    "                start_depth,\n",
    "                start_width,\n",
    "                qr_map_depth,\n",
    "                qr_map_width,\n",
    "                qr_move_depth,\n",
    "                qr_move_width,\n",
    "            ) = experiment_with_timeout(alg, qubit_num, extra_ratio * qubit_num, 10)\n",
    "\n",
    "            # 如果实验成功（不是全零结果），则添加到结果列表中\n",
    "            if not (\n",
    "                start_depth == 0\n",
    "                and start_width == 0\n",
    "                and qr_map_depth == 0\n",
    "                and qr_map_width == 0\n",
    "                and qr_move_depth == 0\n",
    "                and qr_move_width == 0\n",
    "            ):\n",
    "                results.append(\n",
    "                    (\n",
    "                        start_depth,\n",
    "                        start_width,\n",
    "                        qr_map_depth,\n",
    "                        qr_map_width,\n",
    "                        qr_move_depth,\n",
    "                        qr_move_width,\n",
    "                    )\n",
    "                )\n",
    "        return alg, extra_ratio, qubit_num, results\n",
    "\n",
    "    # 使用多线程并发执行所有实验\n",
    "    results_dict = {}\n",
    "    import threading\n",
    "    from concurrent.futures import ThreadPoolExecutor, as_completed\n",
    "\n",
    "    # 降低线程数以避免资源竞争\n",
    "    with ThreadPoolExecutor(max_workers=16) as executor:\n",
    "        # 提交所有任务\n",
    "        future_to_params = {\n",
    "            executor.submit(run_experiments_for_params, alg, extra_ratio, qubit_num): (\n",
    "                alg,\n",
    "                extra_ratio,\n",
    "                qubit_num,\n",
    "            )\n",
    "            for alg, extra_ratio, qubit_num in all_tasks\n",
    "        }\n",
    "\n",
    "        # 收集结果\n",
    "        for future in as_completed(future_to_params):\n",
    "            alg, extra_ratio, qubit_num, valid_results = future.result()\n",
    "            results_dict[(alg, extra_ratio)] = valid_results\n",
    "\n",
    "    # 处理和打印结果，并将均值数据写入文件\n",
    "    with open(csv_file, mode=\"a\", newline=\"\") as file:\n",
    "        writer = csv.writer(file)\n",
    "\n",
    "        for alg in [\"bv\", \"vqa\", \"qaoa\", \"qft\", \"mul\", \"rd\", \"xor\"]:\n",
    "            for extra_ratio in [0.1, 0.2, 0.3]:\n",
    "                qubit_num = 30\n",
    "                valid_results = results_dict.get((alg, extra_ratio), [])\n",
    "\n",
    "                print(\n",
    "                    f\"-- 参数: {alg} 算法, 额外比特比例 {extra_ratio}, 量子比特数量 {qubit_num} --\"\n",
    "                )\n",
    "\n",
    "                # 计算平均值\n",
    "                if valid_results:\n",
    "                    avg_start_depth = sum(r[0] for r in valid_results) / len(\n",
    "                        valid_results\n",
    "                    )\n",
    "                    avg_start_width = sum(r[1] for r in valid_results) / len(\n",
    "                        valid_results\n",
    "                    )\n",
    "                    avg_qr_map_depth = sum(r[2] for r in valid_results) / len(\n",
    "                        valid_results\n",
    "                    )\n",
    "                    avg_qr_map_width = sum(r[3] for r in valid_results) / len(\n",
    "                        valid_results\n",
    "                    )\n",
    "                    avg_qr_move_depth = sum(r[4] for r in valid_results) / len(\n",
    "                        valid_results\n",
    "                    )\n",
    "                    avg_qr_move_width = sum(r[5] for r in valid_results) / len(\n",
    "                        valid_results\n",
    "                    )\n",
    "\n",
    "                    print(\n",
    "                        f\"平均值: {avg_start_depth}, {avg_start_width}, {avg_qr_map_depth}, {avg_qr_map_width}, {avg_qr_move_depth}, {avg_qr_move_width}\"\n",
    "                    )\n",
    "                    print(f\"有效实验次数: {len(valid_results)}\")\n",
    "\n",
    "                    # 将结果写入CSV文件\n",
    "                    writer.writerow(\n",
    "                        [\n",
    "                            alg,\n",
    "                            extra_ratio,\n",
    "                            qubit_num,\n",
    "                            avg_start_depth,\n",
    "                            avg_start_width,\n",
    "                            avg_qr_map_depth,\n",
    "                            avg_qr_map_width,\n",
    "                            avg_qr_move_depth,\n",
    "                            avg_qr_move_width,\n",
    "                            len(valid_results),\n",
    "                        ]\n",
    "                    )\n",
    "                else:\n",
    "                    print(\"所有实验都失败了，无法计算平均值\")\n",
    "                    # 即使实验失败，也记录到文件中\n",
    "                    writer.writerow([alg, extra_ratio, qubit_num, 0, 0, 0, 0, 0, 0, 0])\n",
    "\n",
    "\n",
    "experiment_var_extra_ratio_alg()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
